package com.ndhutu.ee.util.pay.wx;

import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.ndhutu.ee.util.pay.Notify;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信支付工具类
 * @Author Shane
 * @Date 2019/12/12 15:16
 * @param
 * @return
 **/
public class WxPayUtil {
    private static Logger log = LoggerFactory.getLogger(WxPayUtil.class);

    /**
     * 支付下单
     * @Author Shane
     * @Date 2019/12/12 15:46
     * @param orderNumber   业务订单号
     * @param amount        订单金额，单位分
     * @param body          商品描述
     * @param detail        商品详情
     * @return
     **/
    public static Map<String, String> order(WxPayConfig config, String orderNumber, Integer amount, String body, String detail) throws Exception{
        WXPay wxpay = new WXPay(config);

        Map<String, String> params = new HashMap<String, String>();
        params.put("body", body);
        params.put("detail", detail);
        params.put("out_trade_no", orderNumber);
        params.put("total_fee", amount+"");
        params.put("spbill_create_ip", config.getSpbillCreateIp());
        params.put("notify_url", config.getNotifyUrl());
        params.put("trade_type", "APP");

        Map<String, String> resp = wxpay.unifiedOrder(params);
        if("SUCCESS".equals(resp.get("return_code")) && "SUCCESS".equals(resp.get("result_code"))){
            //重新生成签名
            params = new HashMap<>();
            params.put("appid", resp.get("appid"));
            params.put("partnerid", resp.get("mch_id"));
            params.put("prepayid", resp.get("prepay_id"));
            params.put("noncestr", resp.get("nonce_str"));
            params.put("timestamp", System.currentTimeMillis()/1000+"");
            params.put("package", "Sign=WXPay");

            String sign = WXPayUtil.generateSignature(params, config.getKey());
            params.put("sign", sign);
            params.remove("package");

            return params;
        }else{
            log.error("微信支付下单失败，return_msg："+resp.get("return_msg"));
            throw new Exception();
        }
    }

    /**
     * 支付回调
     * @Author Shane
     * @Date 2019/12/12 16:05
     * @param
     * @return
     **/
    public static String notify(HttpServletRequest request, WxPayConfig config, Notify notify) throws Exception{
        Map<String, String> params = new HashMap<>();

        InputStream is = request.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = br.readLine()) != null){
            sb.append(line + "\n");
        }
        is.close();

        String resultXml = sb.toString();
        params = WXPayUtil.xmlToMap(resultXml);
        log.debug("支付宝支付回调参数："+ JSONObject.toJSONString(params));

        //签名验证
        WXPay wxpay = new WXPay(config);
        boolean flag = wxpay.isPayResultNotifySignatureValid(params);
        if(flag){
            if("SUCCESS".equals(params.get("trade_state"))){
                String orderNumber = params.get("out_trade_no");
                Integer amount = Integer.parseInt(params.get("total_fee"));

                //统一回调
                notify.handleNotify(orderNumber, amount);

                params = new HashMap<>();
                params.put("return_code", "SUCCESS");
                params.put("return_msg", "OK");
                log.info("订单" + orderNumber + "微信回调成功");
            }
            return WXPayUtil.mapToXml(params);
        }

        return null;
    }

    /**
     * 获取回调请求参数
     * @param request
     * @return
     * @throws Exception
     */
    public static Map<String, String> getNotifyRequestParams(HttpServletRequest request) throws Exception{
        Map<String, String> params = new HashMap<>();

        InputStream is = request.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = br.readLine()) != null){
            sb.append(line + "\n");
        }
        is.close();

        String resultXml = sb.toString();
        params = WXPayUtil.xmlToMap(resultXml);
        log.debug("支付宝支付回调参数："+ JSONObject.toJSONString(params));

        return params;
    }

    /**
     * 校验回调请求
     * @param params    回调请求参数
     * @param config
     * @param notify
     * @return
     * @throws Exception
     */
    public static String verifyNotifyRequest(Map<String, String> params, WxPayConfig config, Notify notify) throws Exception{
        //签名验证
        WXPay wxpay = new WXPay(config);
        boolean flag = wxpay.isPayResultNotifySignatureValid(params);
        if(flag){
            if("SUCCESS".equals(params.get("trade_state"))){
                String orderNumber = params.get("out_trade_no");
                Integer amount = Integer.parseInt(params.get("total_fee"));

                //统一回调
                notify.handleNotify(orderNumber, amount);

                params = new HashMap<>();
                params.put("return_code", "SUCCESS");
                params.put("return_msg", "OK");
                log.info("订单" + orderNumber + "微信回调成功");
            }
            return WXPayUtil.mapToXml(params);
        }

        return null;
    }
}
